package com_.dxy_test_.testgeotools;

import org.geotools.geojson.geom.GeometryJSON;
import org.locationtech.jts.geom.Coordinate;
import org.locationtech.jts.geom.Geometry;
import org.locationtech.jts.geom.GeometryFactory;
import org.locationtech.jts.io.ParseException;
import org.locationtech.jts.io.WKTReader;
import org.locationtech.jts.operation.buffer.BufferOp;
import org.locationtech.jts.operation.buffer.BufferParameters;

import java.io.IOException;
import java.io.StringReader;
import java.io.StringWriter;

/**
 * @Description 地理空间工具类
 * @Author dangxianyue
 * @Date 2024/6/10 15:21
 */
public class GeoUtil {

    // 地球平均半径（米）
    public static final double EARTH_RADIUS = 6371393;

    /**
     * 构造点
     * @param lon 经度
     * @param lat 纬度
     * @return WKT数据
     */
    public static String buildPoint(double lon, double lat) {
        return buildPoint(new Coordinate(lon, lat));
    }

    /**
     * 构造点
     * @param coordinate 坐标信息
     * @return WKT数据
     */
    public static String buildPoint(Coordinate coordinate) {
        GeometryFactory gf = new GeometryFactory();
        Geometry geometry = gf.createPoint(coordinate);
        return geometry.toText();
    }

    /**
     * 构造线
     * @param coordinates 坐标点信息数组
     * @return WKT数据
     */
    public static String buildLine(Coordinate[] coordinates) {
        GeometryFactory gf = new GeometryFactory();
        Geometry geometry = gf.createLineString(coordinates);
        return geometry.toText();
    }

    /**
     * 构造线
     * @param lineLonLat 坐标点信息数组
     * @return WKT数据
     */
    public static String buildLine(double[][] lineLonLat) {
        Coordinate[] coordinates = new Coordinate[lineLonLat.length];
        for (int i = 0; i < lineLonLat.length; i++) {
            double[] point = lineLonLat[i];
            coordinates[i] = new Coordinate(point[0], point[1]);
        }
        return buildLine(coordinates);
    }

    /**
     * wkt字符串转Geometry对象
     * @param wkt
     * @return
     * @throws ParseException
     */
    public static Geometry wktToGeometry(String wkt) throws ParseException {
        WKTReader reader = new WKTReader();
        return reader.read(wkt);
    }

    /**
     * geoJson字符串转Geometry对象
     * @param geoJson
     * @return
     * @throws IOException
     */
    public static Geometry geoJsonToGeometry(String geoJson) throws IOException {
        StringReader reader = new StringReader(geoJson);
        GeometryJSON geometryJSON = new GeometryJSON();
        return geometryJSON.read(reader);
    }

    /**
     * wkt转GeoJson
     * @param wkt WKT数据
     * @return GeoJson数据
     */
    public static String wktToGeoJson(String wkt) {
        try {
            Geometry geometry = wktToGeometry(wkt);
            StringWriter writer = new StringWriter();
            GeometryJSON g = new GeometryJSON(10);// 精度
            g.write(geometry, writer);
            return writer.toString();
        } catch (ParseException | IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * GeoJson转WKT
     * @param geoJson GeoJson数据，如：
     * {
     *     "type": "Point",
     *     "coordinates": [104.6, 30.1]
     * }
     * @return WKT数据
     */
    public static String geoJsonToWkt(String geoJson) {
        try {
            Geometry geometry = geoJsonToGeometry(geoJson);
            return geometry.toText();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 计算线缓冲区
     * @param lineWkt 线WKT数据
     * @param radius 半径，单位是米
     * @return 缓冲区面WKT数据
     */
    public static String calculateLineBuffer(String lineWkt, double radius) {
        try {
            // 得到Geometry对象
            Geometry geometry = wktToGeometry(lineWkt);

            // 将半径转换成度
            double degree = radius / (2 * Math.PI * EARTH_RADIUS) * 360;

            // 缓冲区建立
            BufferParameters bufParams = new BufferParameters();
            bufParams.setQuadrantSegments(8);  // 设置缓冲区的平滑程度
            bufParams.setEndCapStyle(BufferParameters.CAP_ROUND);  // 设置缓冲区的端点样式
            Geometry bufferGeometry = BufferOp.bufferOp(geometry, degree, bufParams);
            return bufferGeometry.toText();
        } catch (ParseException e) {
            e.printStackTrace();
        }
        return null;
    }

    public static void main(String[] args) {
        // 点
        // String point = buildPoint(113.817563, 23.279552);
        // System.out.println("Point: " + point);
        //
        // String pointJson = wktToGeoJson(point);
        // System.out.println("pointJson: " + pointJson);

        // 线
        // double[][] lineLonLat = new double[][]{
        //         new double[]{113.324553, 23.106414},
        //         new double[]{113.405528, 23.164779},
        //         new double[]{113.473979, 23.1618},
        //         new double[]{113.817563, 23.279552}
        // };
        // String line = buildLine(lineLonLat);
        // System.out.println("Line: " + line);
        //
        // String lineJson = wktToGeoJson(line);
        // System.out.println("lineJson: " + lineJson);

        // geoJson转WKT
        // String geoJson1 = "{\"type\":\"Point\",\"coordinates\":[113.817563,23.279552]}";
        // String geoJson2 = "{\"type\":\"LineString\",\"coordinates\":[[113.817563,23.279552],[113.473979,23.1618],[113.405528,23.164779]]}";
        // String geoJson3 = "{\"type\":\"Feature\",\"geometry\":{\"type\":\"Point\",\"coordinates\":[125.6,10.1]},\"properties\":{\"name\":\"Dinagat Islands\",\"dtg\":1536041936000,\"id\":\"1\"}}";
        // String wkt = geoJsonToWkt(geoJson3);// 暂不支持Feature类型
        // System.out.println("wkt: " + wkt);

        // 缓冲区
        String lineJson = "{\"type\":\"LineString\",\"coordinates\":[[113.817563,23.279552],[113.473979,23.1618],[113.405528,23.164779]]}";
        String lineWkt = geoJsonToWkt(lineJson);
        System.out.println("lineWkt:\n" + lineWkt);
        double radius = 200;
        String bufferWkt = calculateLineBuffer(lineWkt, radius);
        String bufferJson = wktToGeoJson(bufferWkt);
        System.out.println("bufferJson:\n" + bufferJson);
    }



}
